package com.czzapp.xiaoyumemo.model;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;

import com.czzapp.xiaoyumemo.model.Memo.MemoState;
import com.czzapp.xiaoyumemo.provider.MemoProvider;
import com.czzapp.xiaoyumemo.util.MemoNoticeUtil;

public class MemoManager {
	private static boolean sIsInited = false;
	private static final long DAY_MSECONDS = 1000 * 60 * 60 * 24;
	private static final String WHERE_STATE = new String(MemoProvider.STATE + " = ?");
	private static final String WHERE_DAY = new String(MemoProvider.DELAY_DATE + " between ? and ?");
	private static final String WHERE_BEFORE = new String(MemoProvider.STATE + " = " + MemoState.Coming.toInt()
			+ " and " + MemoProvider.DELAY_DATE + " < ?");
	private static final String[] MEMO_PROJECTIONS = new String[] {
		MemoProvider.MEMO_TABLE_ID, MemoProvider.TITLE, MemoProvider.CONTENT,
		MemoProvider.AUDIO_PATH, MemoProvider.INIT_DATE, MemoProvider.DELAY_DATE, 
		MemoProvider.STATE
	};
	private static final int TABLE_ID_PROJECTION_INDEX = 0;
	private static final int TITLE_PROJECTION_INDEX = 1;
	private static final int CONTENT_PROJECTION_INDEX = 2;
	private static final int AUDIO_PATH_PROJECTION_INDEX = 3;
	private static final int INIT_DATE_PROJECTION_INDEX = 4;
	private static final int DELAY_DATE_PROJECTION_INDEX = 5;
	private static final int STATE_PROJECTION_INDEX = 6;
	
	private static final String[] COMING_WHERE_ARGS = new String[] {String.valueOf(MemoProvider.MEMO_STATE_COMING)};
	private static final String[] MISSED_WHERE_ARGS = new String[] {String.valueOf(MemoProvider.MEMO_STATE_MISSED)};
	private static final String[] GONE_WHERE_ARGS = new String[] {String.valueOf(MemoProvider.MEMO_STATE_GONE)};
	
 
	private static MemoManager sInstance = null;
	private String mImei = null;
	private List<MemoManagerListener> mListeners = new ArrayList<MemoManagerListener>();
	private Context mContext = null;
	
	public static void init(Context context) {
		if(sIsInited) {
			return;
		}
		sIsInited = true;
		sInstance = new MemoManager(context);
		AudioManager.init(context);
		List<Memo> memoList = MemoManager.getInstance().getCurrentMissedMemos();
		for(Memo memo : memoList) {
			MemoManager.getInstance().missMemo(memo);
			MemoNoticeUtil.addNotice(context, memo);
		}
		memoList = MemoManager.getInstance().getComingMemoList();
		for(Memo memo : memoList) {
			MemoNoticeUtil.addNotice(context, memo);
		}
	}
	
	//注意，在未init的情况下调用将返回null
	public static MemoManager getInstance() {
		return sInstance;
	}
	
	private MemoManager(Context context) {
		mContext = context;
	}
	
	public String getImei() {
		return mImei;
	}
	
	public void setImei(String imei) {
		mImei = imei;
	}
	
	public List<Memo> getComingMemoList() {
		List<Memo> result = new ArrayList<Memo>();
		Cursor cursor = mContext.getContentResolver().query(MemoProvider.MEMO_CONTENT_URI,
				MEMO_PROJECTIONS,
				WHERE_STATE,
				COMING_WHERE_ARGS,
				null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				do {
					int id = cursor.getInt(TABLE_ID_PROJECTION_INDEX);
					String title = cursor.getString(TITLE_PROJECTION_INDEX);
					String contetn = cursor.getString(CONTENT_PROJECTION_INDEX);
					String audioPath = cursor.getString(AUDIO_PATH_PROJECTION_INDEX);
					long initDate = cursor.getLong(INIT_DATE_PROJECTION_INDEX);
					long delayDate = cursor.getLong(DELAY_DATE_PROJECTION_INDEX);
					int state = cursor.getInt(STATE_PROJECTION_INDEX);
					Memo memo = new Memo(id, title, contetn, audioPath, new Date(initDate), new Date(delayDate), Memo.MemoState.intToMemoState(state));
					result.add(memo);
				} while(cursor.moveToNext());
			}
			cursor.close();
			cursor = null;
		}
		return result;
	}
	
	public List<Memo> getMissedMemoList() {
		List<Memo> result = new ArrayList<Memo>();
		Cursor cursor = mContext.getContentResolver().query(MemoProvider.MEMO_CONTENT_URI,
				MEMO_PROJECTIONS,
				WHERE_STATE,
				MISSED_WHERE_ARGS,
				null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				do {
					int id = cursor.getInt(TABLE_ID_PROJECTION_INDEX);
					String title = cursor.getString(TITLE_PROJECTION_INDEX);
					String contetn = cursor.getString(CONTENT_PROJECTION_INDEX);
					String audioPath = cursor.getString(AUDIO_PATH_PROJECTION_INDEX);
					long initDate = cursor.getLong(INIT_DATE_PROJECTION_INDEX);
					long delayDate = cursor.getLong(DELAY_DATE_PROJECTION_INDEX);
					int state = cursor.getInt(STATE_PROJECTION_INDEX);
					Memo memo = new Memo(id, title, contetn, audioPath, new Date(initDate), new Date(delayDate), Memo.MemoState.intToMemoState(state));
					result.add(memo);
				} while(cursor.moveToNext());
			}
			cursor.close();
			cursor = null;
		}
		return result;
	}
	
	public List<Memo> getGoneMemoList() {
		List<Memo> result = new ArrayList<Memo>();
		Cursor cursor = mContext.getContentResolver().query(MemoProvider.MEMO_CONTENT_URI,
				MEMO_PROJECTIONS,
				WHERE_STATE,
				GONE_WHERE_ARGS,
				null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				do {
					int id = cursor.getInt(TABLE_ID_PROJECTION_INDEX);
					String title = cursor.getString(TITLE_PROJECTION_INDEX);
					String contetn = cursor.getString(CONTENT_PROJECTION_INDEX);
					String audioPath = cursor.getString(AUDIO_PATH_PROJECTION_INDEX);
					long initDate = cursor.getLong(INIT_DATE_PROJECTION_INDEX);
					long delayDate = cursor.getLong(DELAY_DATE_PROJECTION_INDEX);
					int state = cursor.getInt(STATE_PROJECTION_INDEX);
					Memo memo = new Memo(id, title, contetn, audioPath, new Date(initDate), new Date(delayDate), Memo.MemoState.intToMemoState(state));
					result.add(memo);
				} while(cursor.moveToNext());
			}
			cursor.close();
			cursor = null;
		}
		return result;
	}
	
	public Memo addMemo(String title, String content, String audioPath, Date initDate) {
		ContentValues memoContentValues = new ContentValues();
		memoContentValues.put(MemoProvider.TITLE, title);
		memoContentValues.put(MemoProvider.CONTENT, content);
		memoContentValues.put(MemoProvider.AUDIO_PATH, audioPath);
		long initDateLong = initDate.getTime();
		memoContentValues.put(MemoProvider.INIT_DATE, initDateLong);
		memoContentValues.put(MemoProvider.DELAY_DATE, initDateLong);
		memoContentValues.put(MemoProvider.STATE, String.valueOf(MemoState.Coming.toInt()));
		Uri newMemoUri = mContext.getContentResolver().insert(MemoProvider.MEMO_CONTENT_URI, memoContentValues);
		if(newMemoUri != null) {
			int id = Integer.parseInt(newMemoUri.getPathSegments().get(1));
			Memo memo = new Memo(id, title, content, audioPath, initDate, initDate, MemoState.Coming);
			MemoNoticeUtil.addNotice(mContext, memo);
			AudioManager.getInstance().addAudioRef(audioPath);
			onComingMemosChanged();
			return memo;
		}
		else {
			return null;
		}
	}
	
	public void deleteMemo(Memo memo) {
		Uri memoUri = ContentUris.withAppendedId(MemoProvider.MEMO_CONTENT_URI, memo.getId());
		int memoCount = mContext.getContentResolver().delete(memoUri, null, null);
		if(memoCount > 0) {
			if(memo.getState() == MemoState.Coming) {
				onComingMemosChanged();
				MemoNoticeUtil.delNotice(mContext, memo);
			}
			else if(memo.getState() == MemoState.Missed) {
				onMissedMemosChanged();
			}
			else {
				onGoneMemosChanged();
			}
			AudioManager.getInstance().delAudioRef(memo.getAudioPath());
		}
	}
	
	//只有memo的state为Coming才能进行这个操作，而其它的memo进入编辑的时候，应该是创建新的memo，
	//复制除了id和date之外的内容
	public void upateMemo(Memo memo, Date delayDate) {
		if(memo.getState() == MemoState.Coming) {
			memo.setDelayDate(delayDate);
			long delayDateLong = delayDate.getTime();
			ContentValues memoContentValues = new ContentValues();
			memoContentValues.put(MemoProvider.DELAY_DATE, delayDateLong);
			Uri memoUri = ContentUris.withAppendedId(MemoProvider.MEMO_CONTENT_URI, memo.getId());
			int memoCount = mContext.getContentResolver().update(memoUri, memoContentValues, null, null);
			if(memoCount > 0) {
				onComingMemosChanged();
				MemoNoticeUtil.addNotice(mContext, memo);
			}
		}
	}
	
	public void checkMemo(Memo memo) {
		MemoState state = memo.getState();
		if(state == MemoState.Coming || state == MemoState.Missed) {
			memo.check();
			ContentValues memoContentValues = new ContentValues();
			memoContentValues.put(MemoProvider.STATE, MemoState.Gone.toInt());
			Uri memoUri = ContentUris.withAppendedId(MemoProvider.MEMO_CONTENT_URI, memo.getId());
			mContext.getContentResolver().update(memoUri, memoContentValues, null, null);
			if(state == MemoState.Coming) {
				onComingMemosChanged();
				onGoneMemosChanged();
			}
			else {
				onMissedMemosChanged();
				onGoneMemosChanged();
			}
		}
	}
	
	public void missMemo(Memo memo) {
		MemoState state = memo.getState();
		if(state == MemoState.Coming) {
			memo.miss();
			ContentValues memoContentValues = new ContentValues();
			memoContentValues.put(MemoProvider.STATE, MemoState.Missed.toInt());
			Uri memoUri = ContentUris.withAppendedId(MemoProvider.MEMO_CONTENT_URI, memo.getId());
			mContext.getContentResolver().update(memoUri, memoContentValues, null, null);
			onComingMemosChanged();
			onMissedMemosChanged();
		}
	}
	
	public Memo getMemoById(int memoId) {
		Memo result = null;
		Uri memoUri = ContentUris.withAppendedId(MemoProvider.MEMO_CONTENT_URI, memoId);
		Cursor cursor = mContext.getContentResolver().query(memoUri,
				MEMO_PROJECTIONS,
				null,
				null,
				null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				int id = cursor.getInt(TABLE_ID_PROJECTION_INDEX);
				String title = cursor.getString(TITLE_PROJECTION_INDEX);
				String contetn = cursor.getString(CONTENT_PROJECTION_INDEX);
				String audioPath = cursor.getString(AUDIO_PATH_PROJECTION_INDEX);
				long initDate = cursor.getLong(INIT_DATE_PROJECTION_INDEX);
				long delayDate = cursor.getLong(DELAY_DATE_PROJECTION_INDEX);
				int state = cursor.getInt(STATE_PROJECTION_INDEX);
				result = new Memo(id, title, contetn, audioPath, new Date(initDate), new Date(delayDate), Memo.MemoState.intToMemoState(state));
			}
			cursor.close();
		}
		return result;
	}
	
	public List<Memo> getMemosByDate(Calendar calendar) {
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		Date todayZero = calendar.getTime();
		long todayZeroLong = todayZero.getTime();
		long yesterday = todayZeroLong - 1;
		long tomorrow = todayZeroLong + DAY_MSECONDS;
		List<Memo> result = new ArrayList<Memo>();
		Cursor cursor = mContext.getContentResolver().query(MemoProvider.MEMO_CONTENT_URI,
				MEMO_PROJECTIONS,
				WHERE_DAY,
				new String[] {String.valueOf(yesterday), String.valueOf(tomorrow)},
				null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				do {
					int id = cursor.getInt(TABLE_ID_PROJECTION_INDEX);
					String title = cursor.getString(TITLE_PROJECTION_INDEX);
					String contetn = cursor.getString(CONTENT_PROJECTION_INDEX);
					String audioPath = cursor.getString(AUDIO_PATH_PROJECTION_INDEX);
					long initDate = cursor.getLong(INIT_DATE_PROJECTION_INDEX);
					long delayDate = cursor.getLong(DELAY_DATE_PROJECTION_INDEX);
					int state = cursor.getInt(STATE_PROJECTION_INDEX);
					Memo memo = new Memo(id, title, contetn, audioPath, new Date(initDate), new Date(delayDate), Memo.MemoState.intToMemoState(state));
					result.add(memo);
				} while(cursor.moveToNext());
			}
			cursor.close();
			cursor = null;
		}
		return result;
	}
	
	public List<Memo> getCurrentMissedMemos() {
		List<Memo> result = new ArrayList<Memo>();
		Cursor cursor = mContext.getContentResolver().query(MemoProvider.MEMO_CONTENT_URI,
				MEMO_PROJECTIONS,
				WHERE_BEFORE,
				new String[] {String.valueOf(System.currentTimeMillis())},
				null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				do {
					int id = cursor.getInt(TABLE_ID_PROJECTION_INDEX);
					String title = cursor.getString(TITLE_PROJECTION_INDEX);
					String contetn = cursor.getString(CONTENT_PROJECTION_INDEX);
					String audioPath = cursor.getString(AUDIO_PATH_PROJECTION_INDEX);
					long initDate = cursor.getLong(INIT_DATE_PROJECTION_INDEX);
					long delayDate = cursor.getLong(DELAY_DATE_PROJECTION_INDEX);
					int state = cursor.getInt(STATE_PROJECTION_INDEX);
					Memo memo = new Memo(id, title, contetn, audioPath, new Date(initDate), new Date(delayDate), Memo.MemoState.intToMemoState(state));
					result.add(memo);
				} while(cursor.moveToNext());
			}
			cursor.close();
			cursor = null;
		}
		return result;
	}
	
	public void onComingMemosChanged() {
		for(MemoManagerListener listener : mListeners) {
			listener.onComingMemoListChanged();
		}
	}
	
	public void onMissedMemosChanged() {
		for(MemoManagerListener listener : mListeners) {
			listener.onMissedMemoListChanged();
		}
	}
	
	public void onGoneMemosChanged() {
		for(MemoManagerListener listener : mListeners) {
			listener.onGoneMemoListChanged();
		}
	}
	
	public void addListener(MemoManagerListener listener) {
		if(!mListeners.contains(listener)) {
			mListeners.add(listener);
		}
	}
	
	public void delListener(MemoManagerListener listener) {
		if(mListeners.contains(listener)) {
			mListeners.remove(listener);
		}
	}
}
